import { menu } from '../../../app/decorator';
import BasePlay from './base/BasePlay';

const { ccclass, property, requireComponent } = cc._decorator;

interface IComplete {
    (success?: boolean): void
}

@ccclass
@menu(__filename)
@requireComponent(sp.Skeleton)
export default class PlaySpine extends BasePlay {
    @property
    private __animation: string = '<None>';
    @property({
        visible: false
    })
    get animation() { return this.__animation; }
    set animation(value) {
        this.__animation = value;
        if (CC_EDITOR) {
            0;
        } else {
            this._play();
        }
    }

    @property({
        tooltip: CC_DEV && '在编辑器中不可编辑,跟随Skeleton中的Animation属性\n运行中可以通过代码设置',
        visible: true
    })
    get _animation() {
        return this.__animation;
    }

    private _timeScale = 1;
    get timeScale() {
        if (this._currSpine && this._timeScale != this._currSpine.timeScale) this._timeScale = this._currSpine.timeScale;
        return this._timeScale;
    }

    set timeScale(scale) {
        if (this._currSpine) this._currSpine.timeScale = scale;
        this._timeScale = scale;
    }

    static Event = {
        SpinePlay: 'spinePlay',
        SpineStop: 'spineStop',
        SpinePause: 'spinePause',
        SpineResume: 'spineResume',
        SpineComplete: 'spineComplete',

        SpineInterrupt: 'spineInterrupt',
        SpineDispose: 'spineDispose',
        SpineEvent: 'spineEvent'
    };

    // spine组件
    private __currSpine: sp.Skeleton = null;
    private get _currSpine(): sp.Skeleton {
        if (!this.__currSpine) this.__currSpine = this.node.getComponent(sp.Skeleton);
        return this.__currSpine;
    }
    // 是否完成
    private _isCompelte = false;
    // 完成控制变量
    private _compelteCtr = false;
    // 完成回调
    private _completeCallback: IComplete = null;

    onLoad() {
        const spine = this._currSpine;
        this._currSpine.loop = false;
        this._currSpine.paused = true;
        this._currSpine.timeScale = this._timeScale;

        // 开始
        spine.setStartListener(() => {
        });
        // 结束
        spine.setEndListener(() => {
        });
        // 完成一次动画
        spine.setCompleteListener(() => {
            this._compelteCtr = true;
        });
        spine.setInterruptListener((trackEntry) => {
            this.node.emit(PlaySpine.Event.SpineInterrupt, trackEntry.animation.name);
        });
        spine.setDisposeListener((trackEntry) => {
            this.node.emit(PlaySpine.Event.SpineDispose, trackEntry.animation.name);
        });
        spine.setEventListener((a, b, c) => {
            this.node.emit(PlaySpine.Event.SpineEvent, a, b, c);
        });

        super.onLoad();
    }

    /**
     * 播放多少次
     * @param loopCount 循环次数
     * @returns 
     */
    protected _play(loopCount?: number): boolean {
        this.stop();

        if (this.animation === '<None>') return false;

        this._isCompelte = false;
        this._compelteCtr = false;
        this._currSpine.paused = true;
        this._currSpine.loop = false;
        this._currSpine.animation = this.animation;

        super.basePlay(0, loopCount);

        return true;
    }

    /**
     * 在_render前被调用，用于设置一些状态
     */
    protected _beforeRender() {
        if (this._compelteCtr === false && this._isCompelte) {
            this._isCompelte = false;
            this._currSpine.animation = this.animation;
        }
    }

    /**
     * 渲染一帧率
     * @returns 全部完成返回false，否则返回true继续渲染
     */
    protected _render(dt: number): boolean {
        if (this._compelteCtr === false) {
            if (CC_EDITOR) {
                CC_EDITOR = false;
                this._currSpine.paused = false;
                this._currSpine['update'](dt);
                this._currSpine.paused = true;
                CC_EDITOR = true;
            } else {
                this._currSpine.paused = false;
                this._currSpine['update'](dt);
                this._currSpine.paused = true;
            }
        }

        return !this.checkComplete();
    }

    /**
     * 检查是否播放完成
     */
    private checkComplete() {
        if (this._compelteCtr) {
            this._isCompelte = true;
            this._compelteCtr = false;

            // 完成一次动画
            if (this._completeCallback) {
                this._completeCallback(true);
            }

            if (!CC_EDITOR) this.node.emit(PlaySpine.Event.SpineComplete, this.animation);

            return true;
        }
        return false;
    }

    /**
     * 播放动画
     * @param name 动作名字
     * @param playTimes 播放次数(默认遵从loop)
     */
    play(name?: string, complete?: IComplete, playTimes = 0, playDelay = 0, loopInterval = 0) {
        this.playDelay = playDelay;
        this.loopInterval = loopInterval;
        // 先停止
        this.stop();

        if (typeof name === 'string') {
            this.__animation = name;
        }
        playTimes = Math.floor(playTimes);
        this._completeCallback = complete || null;

        // 0代表遵从loop
        if (playTimes === 0) playTimes = this.loop ? -1 : 1;

        // 播放失败
        if (!this._play(playTimes - 1)) return false;

        if (!CC_EDITOR) this.node.emit(PlaySpine.Event.SpinePlay, this.animation);

        return true;
    }

    /**
     * 播放一次
     * @param name 动作名字
     */
    playOnce(name?: string, complete?: IComplete, playDelay = 0) {
        return this.play(name, complete, 1, playDelay);
    }

    /**
     * 播放循环
     * @param name 动作名字
     */
    playLoop(name?: string, loopInterval = 0, complete?: IComplete, playDelay = 0) {
        return this.play(name, complete, -1, playDelay, loopInterval);
    }

    stop() {
        if (super.stop()) {
            this._currSpine.paused = true;

            // 完成一次动画的中途被停止了
            if (this._isCompelte === false && this._completeCallback) {
                this._completeCallback(false);
                this._completeCallback = null;
            }

            if (!CC_EDITOR) this.node.emit(PlaySpine.Event.SpineStop, this.animation);
            return true;
        }
        return false;
    }

    pause() {
        if (super.pause()) {
            this._currSpine.paused = true;
            if (!CC_EDITOR) this.node.emit(PlaySpine.Event.SpinePause, this.animation);
            return true;
        }
        return false;
    }

    resume() {
        if (super.resume()) {
            this._currSpine.paused = false;
            if (!CC_EDITOR) this.node.emit(PlaySpine.Event.SpineResume, this.animation);
            return true;
        }
        return false;
    }

    /**
     * 切换皮肤
     */
    setSkin(name: string) {
        this.__currSpine.setSkin(name);
    }

    protected update(dt: number) {
        super.update(dt);

        if (CC_EDITOR && this._currSpine) {
            if (this._currSpine.loop) {
                //@ts-ignore
                Editor.info('不要使用sp.Skeleton的loop属性，请使用playSpine的loop属性代替');
                this._currSpine.loop = false;
                this.loop = true;
            }

            this.__animation = this._currSpine.animation || '<None>';
        }
    }
}
